package com.otto.reggie.controller;

import com.alibaba.druid.sql.ast.expr.SQLCaseExpr;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.otto.reggie.common.CustomException;
import com.otto.reggie.common.R;
import com.otto.reggie.dto.DishDto;
import com.otto.reggie.entity.*;
import com.otto.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.security.Key;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 作者：otto
 * 时间：2022-08-12 13:45:29
 */
@RestController
@Slf4j
@RequestMapping("/dish")
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SetmealService setmealService;

    @Autowired
    private SetmealDishService setmealDishService;

    /**
     * 新增菜品
     *
     * @param dishDto
     * @return
     */
    @PostMapping
    @Transactional
    public R<String> save(@RequestBody DishDto dishDto) {
        log.info("收到需要保存的菜品信息:{}", dishDto.toString());
        //保存菜品中除口味之外的信息
        dishService.save(dishDto);
        //为口味信息中的dishid赋值
        Long dishId = dishDto.getId();
        List<DishFlavor> flavors = dishDto.getFlavors();
        flavors = flavors.stream().map((item) -> {
            item.setDishId(dishId);
            return item;
        }).collect(Collectors.toList());
        //保存菜品口味信息
        dishFlavorService.saveBatch(flavors);

        return R.success("添加菜品成功");
    }

    /**
     * 菜品信息分页查询
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String name) {
        //创建分页
        Page<Dish> dishPage = new Page<>(page, pageSize);
        //构造查询条件
        if (name != null) {
            name = name.trim();
        }

        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(name), Dish::getName, name);
        queryWrapper.orderByDesc(Dish::getSort);
        //构造真正需要传回前端的分页
        Page<DishDto> dishDtoPage = new Page<>(page, pageSize);
        //将原始分页数据查询出来
        dishService.page(dishPage, queryWrapper);
        //利用工具类将带数据的分页复制到代传回分页，除了records属性
        BeanUtils.copyProperties(dishPage, dishDtoPage, "records");
        //将原始分页的records提取出来
        List<Dish> records = dishPage.getRecords();
        //通过stream流遍历原始records，新建dto对象，并复制数据，再利用id查询name赋值
        List<DishDto> list = records.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item, dishDto);
            Long categoryId = item.getCategoryId();
            Category category = categoryService.getById(categoryId);
            if (category != null) {
                dishDto.setCategoryName(category.getName());
            }
            return dishDto;
        }).collect(Collectors.toList());
        //将待传回分页的records属性赋值
        dishDtoPage.setRecords(list);
        return R.success(dishDtoPage);
    }

    /**
     * 根据dishId回显菜品信息
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<DishDto> getById(@PathVariable Long id) {
        log.info("修改id为{}的菜品信息", id);
        //通过dishId查询菜品信息
        Dish dish = dishService.getById(id);
        //通过dishId查询菜品口味
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DishFlavor::getDishId, id);
        List<DishFlavor> list = dishFlavorService.list(queryWrapper);
        DishDto dishDto = new DishDto();
        //将查到的菜品信息赋值给dto
        BeanUtils.copyProperties(dish, dishDto);
        //将口味信息赋值
        dishDto.setFlavors(list);
        return R.success(dishDto);
    }


    /**
     * 修改菜品信息
     *
     * @param dishDto
     * @return
     */
    @PutMapping
    public R<String> updateById(@RequestBody DishDto dishDto) {
        log.info("保存菜品信息 : {},以及菜品的名称: {}", dishDto.toString(), dishDto.getName());

        dishService.updateById(dishDto);
        LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DishFlavor::getDishId, dishDto.getId());
        dishFlavorService.remove(queryWrapper);
        if (dishDto.getFlavors() != null) {
            List<DishFlavor> flavors = dishDto.getFlavors();
            //为每条口味信息设置对应的菜品id
            flavors = flavors.stream().map((item) -> {
                item.setDishId(dishDto.getId());
                return item;
            }).collect(Collectors.toList());
            dishFlavorService.saveBatch(flavors);
        }
        return R.success("保存成功");
    }

    /**
     * 停售菜品
     *
     * @param ids
     * @return
     */
    @PostMapping("/status/0")
    public R<String> stopSell(Long[] ids) {
        //收集所有不能停售的菜品
        ArrayList<String> dishsUnableToStop = new ArrayList<>();
        for (Long id : ids) {
            log.info("收到需要停售的菜品id:" + id);
            //标志是否可以停售
            boolean stopAble = true;


            //1.根据菜品id查到包含该菜品的所有套餐
            //1.1.获取所有套餐的菜品
            List<SetmealDish> setmealDishes = setmealDishService.list();
            //1.2.遍历所有菜品
            for (SetmealDish setmealDish : setmealDishes) {
                //如果有某套餐包含此菜品
                if (setmealDish.getDishId().longValue() == id.longValue()) {
                    Setmeal setmeal = setmealService.getById(setmealDish.getSetmealId());
                    //且包含该菜品的套餐正在售卖
                    if (setmeal.getStatus() == 1) {
                        //修改标志为不可以停售
                        stopAble = false;
                    }
                }
            }
            Dish dish = dishService.getById(id);
            //可以停售
            if (stopAble == true) {
                if (dish.getStatus() != 0) {
                    dish.setStatus(0);
                }
                dishService.updateById(dish);
            } else {
                dishsUnableToStop.add(dish.getName());
            }
        }
        if (dishsUnableToStop.isEmpty()) {
            return R.success("已将全部所选菜品停售");
        } else {
            throw new CustomException("部分菜品因有关联套餐在启售，不能停售" + dishsUnableToStop);
        }

    }

    /**
     * 启售菜品
     *
     * @param ids
     * @return
     */
    @PostMapping("/status/1")
    public R<String> startSell(Long[] ids) {
        if (ids.length == 0) {
            return R.error("没有选中");
        }
        for (Long id : ids) {
            log.info("收到需要启售的菜品id:" + id);
            Dish dish = dishService.getById(id);
            if (dish.getStatus() != 1) {
                dish.setStatus(1);
            }
            dishService.updateById(dish);
        }
        return R.success("已将全部所选菜品启售");
    }

    /**
     * 批量删除菜品
     *
     * @param ids
     * @return
     */
    @DeleteMapping
    public R<String> deleteDishByIds(Long[] ids) {
        //新建一个map，保存不能删的菜品名以及对应包含的套餐名
        HashMap<String, List<String>> dishAndSetmeal = new HashMap<>();
        for (Long id : ids) {
            String dishName = null;
            log.info("收到需要启售的菜品id:" + id);
            //1.检查菜品是否绑定套餐，并创建一个标志
            boolean deleteAble = true;
            //1.1新建一个集合，保存所有包含该菜品的套餐名
            ArrayList<String> setmealInvolveDish = new ArrayList<>();
            //1.2查询所有套餐菜品
            List<SetmealDish> setmealDishes = setmealDishService.list();
            log.info("全部套餐菜品:{}", setmealDishes);
            //1.3遍历所有有菜品，检查是否是该菜品
            for (SetmealDish setmealDish : setmealDishes) {
                log.info("正在比对的套餐:{}", setmealDish.getName());
                log.info("被比较的菜品id-{}，待删除的菜品id-{}", setmealDish.getDishId(), id);
                //1.3.1 如果是该菜品，则通过套餐id查询套餐，将套餐名字加入到集合中
                if (setmealDish.getDishId().longValue() == id.longValue()) {
                    dishName = setmealDish.getName();
                    deleteAble = false;
                    Long setmealId = setmealDish.getSetmealId();
                    Setmeal setmeal = setmealService.getById(setmealId);
                    setmealInvolveDish.add(setmeal.getName());
                }
            }
            if (deleteAble == false) {
                //将菜品名和对应的套餐名加入Map
                dishAndSetmeal.put(dishName, setmealInvolveDish);
            }
            //1.3.2 无套餐有该菜品，可以删除
            if (deleteAble == true) {
                //1.3.2.1删除菜品口味
                LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(DishFlavor::getDishId, id);
                dishFlavorService.remove(queryWrapper);
                //1.3.2.2删除菜品
                dishService.removeById(id);
            }
        }
        if (dishAndSetmeal.isEmpty()) {
            return R.success("已删除全部所选菜品");
        } else {
            throw new CustomException("有以下菜品未删除" + dishAndSetmeal);
        }

    }

    @GetMapping("/list")
    public R<List<DishDto>> list(Long categoryId) {
        log.info("添加套餐展示菜品时收到前端参数分类信息:{}", categoryId);
        //新建查询条件，显示菜品信息
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dish::getCategoryId, categoryId);
//        queryWrapper.eq(Dish::getStatus,1);
        queryWrapper.orderByDesc(Dish::getUpdateTime);
        //获取菜品集合
        List<Dish> list = dishService.list(queryWrapper);
        //便利菜品信息
        List<DishDto> dishDtoList = list.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            //给Dto对象赋值
            BeanUtils.copyProperties(item, dishDto, "flavors");
            //根据菜品id获取口味信息
            Long dishId = item.getId();
            LambdaQueryWrapper<DishFlavor> dishFlavorQueryWrapper = new LambdaQueryWrapper<>();
            dishFlavorQueryWrapper.eq(DishFlavor::getDishId, dishId);
            List<DishFlavor> dishFlavors = dishFlavorService.list(dishFlavorQueryWrapper);
            //赋值口味信息
            dishDto.setFlavors(dishFlavors);
            return dishDto;
        }).collect(Collectors.toList());
        return R.success(dishDtoList);
    }
}
